package androidawn.framework.model;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;

@SuppressWarnings({ "rawtypes", "unchecked" })
public class ObservedCollection<E> implements List<E>{

	private List<E> items = new ArrayList<E>();
	
	private List<ICollectionChangedListener> listeners = new ArrayList<ICollectionChangedListener>();
	
	@Override
	public boolean add(E object) {
		boolean result = items.add(object);
		if(result)
		{
			List list = new ArrayList<E>();
			list.add(object);
			fireCollectionChanged(CollectionEventKind.ADD, list, items.size() - 1, 0);
		}
		return result;
	}
	
	@Override
	public void add(int location, E object) {
		items.add(location, object);
		List list = new ArrayList<E>();
		list.add(object);
		fireCollectionChanged(CollectionEventKind.ADD, list, location, 0);
	}

	
	@Override
	public boolean addAll(Collection<? extends E> collection) {
		boolean result = items.addAll(collection);
		if(result)
		{
			List list = new ArrayList<E>();
			list.addAll(collection);
			fireCollectionChanged(CollectionEventKind.ADD, list, items.size() - 1, 0);
		}
		return result;
	}

	@Override
	public boolean addAll(int location, Collection<? extends E> collection) {
		boolean result = items.addAll(location, collection);
		if(result)
		{
			List list = new ArrayList<E>();
			list.addAll(collection);
			fireCollectionChanged(CollectionEventKind.ADD, list, location, 0);
		}
		return result;
	}

	@Override
	public void clear() {
		items.clear();
		fireCollectionChanged(CollectionEventKind.RESET, null, 0, 0);
	}

	@Override
	public boolean contains(Object object) {
		return items.contains(object);
	}

	@Override
	public boolean containsAll(Collection<?> collection) {
		return items.containsAll(collection);
	}

	@Override
	public E get(int location) {
		return items.get(location);
	}

	@Override
	public int indexOf(Object object) {
		return items.indexOf(object);
	}

	@Override
	public boolean isEmpty() {
		return items.isEmpty();
	}

	@Override
	public Iterator<E> iterator() {
		return items.iterator();
	}

	@Override
	public int lastIndexOf(Object object) {
		return items.lastIndexOf(object);
	}

	@Override
	public ListIterator<E> listIterator() {
		return items.listIterator();
	}

	@Override
	public ListIterator<E> listIterator(int location) {
		return items.listIterator(location);
	}

	@Override
	public E remove(int location) {
		E result = items.remove(location);
		if(result != null)
		{
			List list = new ArrayList<E>();
			list.add(result);
			fireCollectionChanged(CollectionEventKind.REMOVE, list, 0, 0);
		}
		return result;
	}

	@Override
	public boolean remove(Object object) {
		boolean result = items.remove(object);
		if(result)
		{
			List list = new ArrayList<E>();
			list.add(object);
			fireCollectionChanged(CollectionEventKind.REMOVE, list, 0, 0);
		}
		return result;
	}

	@Override
	public boolean removeAll(Collection<?> collection) {
		boolean result = items.removeAll(collection);
		if(result)
		{
			List list = new ArrayList<E>();
			list.addAll(collection);
			fireCollectionChanged(CollectionEventKind.REMOVE, list, 0, 0);
		}
		return result;
	}

	@Override
	public boolean retainAll(Collection<?> arg0) {
		return items.retainAll(arg0);
	}

	@Override
	public E set(int location, E object) {
		E result = items.set(location, object);
		List list = new ArrayList<E>();
		list.add(result);
		fireCollectionChanged(CollectionEventKind.REPLACE, list, location, 0);
		return result;
	}

	@Override
	public int size() {
		return items.size();
	}

	@Override
	public List<E> subList(int start, int end) {
		return items.subList(start, end);
	}

	@Override
	public Object[] toArray() {
		return items.toArray();
	}

	@Override
	public <T> T[] toArray(T[] array) {
		return items.toArray(array);
	}
	
	public void addCollectionChangedListener(ICollectionChangedListener listener)
	{
		if(listeners.contains(listener))
		{
			return;
		}
		listeners.add(listener);
	}
	
	public void removeCollectionChangedListener(ICollectionChangedListener listener)
	{
		listeners.remove(listener);
	}
	
	private void fireCollectionChanged(CollectionEventKind kind, List items, int location, int oldLocation)
	{
		for(ICollectionChangedListener listener : listeners)
		{
			listener.onCollectionChanged(kind, items, location, oldLocation);
		}
	}

}
